package com.zfzs.post.modules.transaction.service.impl;

import com.zfzs.post.modules.transaction.domain.BenefitDay;
import com.zfzs.post.modules.transaction.repository.BenefitDayRepository;
import com.zfzs.post.modules.transaction.service.BenefitDayService;
import com.zfzs.post.modules.transaction.service.dto.BenefitDay4MineDTO;
import com.zfzs.post.modules.transaction.service.dto.BenefitDayQueryCriteria;
import com.zfzs.post.modules.transaction.service.mapper.BenefitDayMapper;
import com.zfzs.post.modules.transaction.service.mybatis.IbatisBenefitDayService;
import com.zfzs.post.utils.PageUtil;
import com.zfzs.post.utils.QueryHelp;
import com.zfzs.post.utils.StringUtils;
import com.zfzs.post.utils.ValidationUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @author wq
 * @date 2019-10-21
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class BenefitDayServiceImpl implements BenefitDayService {

    @Autowired
    private BenefitDayRepository benefitDayRepository;

    @Autowired
    private BenefitDayMapper benefitDayMapper;

    @Autowired
    private IbatisBenefitDayService ibatisBenefitDayService;


    @Override
    public Object queryAll(BenefitDayQueryCriteria criteria, Pageable pageable) {
        Page<BenefitDay> page = benefitDayRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(benefitDayMapper::toDto));
    }

    @Override
    public Object queryAll(BenefitDayQueryCriteria criteria) {
        return benefitDayMapper.toDto(benefitDayRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    public BenefitDay findById(Long benefitId) {
        Optional<BenefitDay> benefitDay = benefitDayRepository.findById(benefitId);
        ValidationUtil.isNull(benefitDay, "BenefitDay", "benefitId", benefitId);
        return benefitDay.get();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BenefitDay create(BenefitDay resources) {
        return benefitDayRepository.save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(BenefitDay resources) {
        Optional<BenefitDay> optionalBenefitDay = benefitDayRepository.findById(resources.getBenefitId());
        ValidationUtil.isNull(optionalBenefitDay, "BenefitDay", "id", resources.getBenefitId());
        BenefitDay benefitDay = optionalBenefitDay.get();
        benefitDay.copy(resources);
        benefitDay.setUpdateTime(new Date());
        benefitDayRepository.save(benefitDay);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long benefitId) {
        benefitDayRepository.deleteById(benefitId);
    }

    @Override
    public List<BenefitDay> findByAgentId(Long agentId) {
        return benefitDayRepository.findByAgentId(agentId);
    }

    @Override
    public List<BenefitDay> findByAgentId(Long agentId, String startDate, String endDate) {
        return benefitDayRepository.findByAgentId(agentId, startDate, endDate);
    }

    @Override
    public List<BenefitDay4MineDTO> findMineDetail(Long agentId, String startDate, String endDate, Integer isSelf, Integer pageNum) {

        List<BenefitDay4MineDTO> mineDetail = ibatisBenefitDayService.findMineDetail(agentId, isSelf, startDate, endDate, pageNum * 10, 10);
        return mineDetail;
    }

    @Override
    public BigDecimal findTeamBenefitByAgentId(Long agentId, String month) {
        return ibatisBenefitDayService.findTeamBenefitByAgentId(agentId, month);
    }

    @Override
    public BigDecimal findSelfBenefitByAgentId(Long agentId, String month) {
        return ibatisBenefitDayService.findSelfBenefitByAgentId(agentId, month);
    }

    @Override
    public BenefitDay findByAgentIdAndDate(Long agentId, String date) {
        return benefitDayRepository.findByAgentIdAndDate(agentId, date);
    }

    @Override
    public Page<BenefitDay> getBenefitPage(BenefitDayQueryCriteria criteria, Integer page, Integer size) {

        Pageable pageable= PageRequest.of(page,size);

        Specification specification = (Specification) (root, cq, cb) -> {

            List<Predicate> list = new ArrayList<>();

            if (criteria.getChannelId() != null) {

                Predicate channelId = cb.equal(root.get("channelId"),criteria.getChannelId());
                list.add(channelId);
            }

            if (StringUtils.isNotBlank(criteria.getStartDate()) && StringUtils.isNotBlank(criteria.getEndDate())) {

                Predicate benefitDate = cb.between(root.get("benefitDate").as(String.class), criteria.getStartDate(),criteria.getEndDate());
                list.add(benefitDate);
            }

            if(criteria.getAgentIds()!=null && !criteria.getAgentIds().isEmpty()){
                Predicate agentIds = root.get("agentId").in(criteria.getAgentIds());
                list.add(agentIds);
            }

            Order descDate = cb.desc(root.get("benefitDate"));
            Predicate[] predicates = list.toArray(new Predicate[list.size()]);
            cq.where( cb.and(predicates));
            cq.orderBy(descDate);
            return cq.getRestriction();
        };
        return benefitDayRepository.findAll(specification,pageable);
    }

    @Override
    public String getBenefit(List<Long> ids, String startDate, String endDate) {
        return benefitDayRepository.getBenefit(ids,startDate,endDate);
    }
}